﻿using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;



namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
    public class CallerMemberNameAttribute : Attribute
    {

    }


}

namespace  Trade.Journal
{

    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public abstract class BindableBase : INotifyPropertyChanged//,ISerializable
    {
        protected virtual bool UseDynamicInvoke { get; }

        /// <summary>
        /// 
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="storage"></param>
        /// <param name="value"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        protected void SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
        {
            //if (object.Equals(storage, value)) return false;

            T old = storage;
            storage = value;
            OnPropertyChanged<T>(propertyName, old, value);

            if (!string.IsNullOrEmpty(propertyName))
                NotifyPropertyChanged(propertyName);
        }

     

        protected void SetProperty<T>(ref T storage, T value, string propertyName, params string[] propertiesNotify)
        { 
            T old = storage;
            storage = value; 

            if (!string.IsNullOrEmpty(propertyName))
            { 
                NotifyPropertyChanged(propertyName);
                OnPropertyChanged<T>(propertyName, old, value);
            }

            if (propertiesNotify == null || propertiesNotify.Length == 0)
                return;

            foreach (string pn in propertiesNotify)
            {
                if (!string.IsNullOrEmpty(pn))
                    NotifyPropertyChanged(pn);
            }
        }

        protected void SetProperty<T>(ref T storage, T value, params string[] propertiesNotify)
        {
            //if (object.Equals(storage, value)) return false;

            T old = storage;
            storage = value;

            if (propertiesNotify == null || propertiesNotify.Length == 0)
                return;

            foreach (string propertyName in propertiesNotify)
            {
                OnPropertyChanged<T>(propertyName, old, value);

                if (string.IsNullOrEmpty(propertyName)) return;

                NotifyPropertyChanged(propertyName);
            }

        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="propertyName"></param>
        protected void NotifyPropertyChanged([CallerMemberName]string propertyName = null)
        {
            if (!UseDynamicInvoke)
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            else if (UseDynamicInvoke && PropertyChanged != null)
            {
                Delegate[] list = PropertyChanged.GetInvocationList();
                foreach (Delegate item in list)
                {
                    try { item.DynamicInvoke(this, new PropertyChangedEventArgs(propertyName)); }
                    catch (Exception e) { throw; }
                }
            }
            //if (PropertyChanged != null)
            //{
            //    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            //}
        }



        protected virtual void OnPropertyChanged<T>(string propertyName, T oldValue, T newValue)
        {

        }


        protected virtual void OnGetObjectData(SerializationInfo info, StreamingContext context)
        {

        }

        //void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        //{
        //    OnGetObjectData(info,context);
        //}
    }
}
